<template>
  <div class="panel-tab__content">
    <t-table :data="elementListenersList" size="small" bordered stripe :columns="elementListenersColumns" row-key="index">
      <template #index="{ rowIndex }">  
        {{ rowIndex + 1 }}
      </template>
      <template #event="{ row }">  
        {{ listenerEventTypeObject[row.event] }}
      </template>
      <template #listenerType="{ row }">  
        {{ listenerTypeObject[row.listenerType] }}
      </template>
      <template #operation="{ row ,rowIndex }">
        <t-link size="small" style="margin-right: 4px;" theme="primary" @click="openListenerForm(row, rowIndex)"
          >编辑</t-link
        >
        <t-link size="small" theme="danger" @click="removeListener(row,rowIndex)"
          >移除</t-link
        >
      </template>
    </t-table>
    <div class="element-drawer__button">
      <t-button
        theme="primary"
        preIcon="ep:plus"
        size="small"
        block
        @click="openListenerForm(null)"
      >添加监听器</t-button>
      <t-button
        theme="success"
        preIcon="ep:select"
        size="small"
        block
        @click="openProcessListenerDialog"
      >选择监听器</t-button>
    </div>

    <!-- 监听器 编辑/创建 部分 -->
    <t-drawer
      v-model:visible="listenerFormModelVisible"
      header="任务监听器"
      :size="`${width}px`"
      append-to-body
      destroy-on-close
      :footer="false"
    >
      <t-form size="small" :data="listenerForm" label-width="96px" ref="listenerFormRef">
        <t-form-item
          label="事件类型"
          name="event"
          :rules="[{ required: true, message: '请输入事件类型' }]"
        >
          <t-select v-model:value="listenerForm.event">
            <t-option
              v-for="i in Object.keys(listenerEventTypeObject)"
              :key="i"
              :label="listenerEventTypeObject[i]"
              :value="i"
            />
          </t-select>
        </t-form-item>
        <t-form-item
          label="监听器ID"
          name="id"
          :rules="[{ required: true, message: '请输入监听器ID' }]"
        >
          <t-input v-model:value="listenerForm.id" clearable />
        </t-form-item>
        <t-form-item
          label="监听器类型"
          name="listenerType"
          :rules="[{ required: true, message: '请输入监听器类型' }]"
        >
          <t-select v-model:value="listenerForm.listenerType">
            <t-option
              v-for="i in Object.keys(listenerTypeObject)"
              :key="i"
              :label="listenerTypeObject[i]"
              :value="i"
            />
          </t-select>
        </t-form-item>
        <t-form-item
          v-if="listenerForm.listenerType === 'classListener'"
          label="Java类"
          name="class"
          key="listener-class"
          :rules="[{ required: true, message: '请输入Java类' }]"
        >
          <t-input v-model:value="listenerForm.class" clearable />
        </t-form-item>
        <t-form-item
          v-if="listenerForm.listenerType === 'expressionListener'"
          label="表达式"
          name="expression"
          key="listener-expression"
          :rules="[{ required: true, message: '请输入表达式' }]"
        >
          <t-input v-model:value="listenerForm.expression" clearable />
        </t-form-item>
        <t-form-item
          v-if="listenerForm.listenerType === 'delegateExpressionListener'"
          label="代理表达式"
          name="delegateExpression"
          key="listener-delegate"
          :rules="[{ required: true, message: '请输入代理表达式' }]"
        >
          <t-input v-model:value="listenerForm.delegateExpression" clearable />
        </t-form-item>
        <template v-if="listenerForm.listenerType === 'scriptListener'">
          <t-form-item
            label="脚本格式"
            name="scriptFormat"
            key="listener-script-format"
            :rules="[{ required: true,  message: '请填写脚本格式' }]"
          >
            <t-input v-model:value="listenerForm.scriptFormat" clearable />
          </t-form-item>
          <t-form-item
            label="脚本类型"
            name="scriptType"
            key="listener-script-type"
            :rules="[{ required: true,  message: '请选择脚本类型' }]"
          >
            <t-select v-model:value="listenerForm.scriptType">
              <t-option label="内联脚本" value="inlineScript" />
              <t-option label="外部脚本" value="externalScript" />
            </t-select>
          </t-form-item>
          <t-form-item
            v-if="listenerForm.scriptType === 'inlineScript'"
            label="脚本内容"
            name="value"
            key="listener-script"
            :rules="[{ required: true, message: '请填写脚本内容' }]"
          >
            <t-input v-model:value="listenerForm.value" clearable />
          </t-form-item>
          <t-form-item
            v-if="listenerForm.scriptType === 'externalScript'"
            label="资源地址"
            name="resource"
            key="listener-resource"
            :rules="[{ required: true,  message: '请填写资源地址' }]"
          >
            <t-input v-model:value="listenerForm.resource" clearable />
          </t-form-item>
        </template>

        <template v-if="listenerForm.event === 'timeout'">
          <t-form-item label="定时器类型" name="eventDefinitionType" key="eventDefinitionType">
            <t-select v-model:value="listenerForm.eventDefinitionType">
              <t-option label="日期" value="date" />
              <t-option label="持续时长" value="duration" />
              <t-option label="循环" value="cycle" />
              <t-option label="无" value="null" />
            </t-select>
          </t-form-item>
          <t-form-item
            v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
            label="定时器"
            name="eventTimeDefinitions"
            key="eventTimeDefinitions"
            :rules="[{ required: true,  message: '请填写定时器配置' }]"
          >
            <t-input v-model:value="listenerForm.eventTimeDefinitions" clearable />
          </t-form-item>
        </template>
      </t-form>

      <t-divider />
      <p class="listener-filed__title">
        <span><Icon icon="ep:menu" />注入字段：</span>
        <t-button size="small" theme="primary" @click="openListenerFieldForm(null)"
          >添加字段</t-button
        >
      </p>
      <t-table
        :data="fieldsListOfListener"
        size="small"
        max-height="240"
        fit
        bordered
        stripe
        style="flex: none"
        :columns="columns"
      >
        <template #index="{ rowIndex }">  
          {{ rowIndex + 1 }}
        </template>
        <template #fieldType="{ row }">  
          {{ fieldTypeObject[row.fieldType] }}
        </template>
        <template #string="{ row }">  
        {{ row.string || row.expression }}
      </template>
      <template #operation="{ row ,rowIndex }">
        <t-link size="small" style="margin-right: 4px;" theme="primary" @click="openListenerFieldForm(row, rowIndex)"
          >编辑</t-link>
            
        <t-link
          size="small"
          theme="danger"
          @click="removeListenerField(row,rowIndex)"
          >移除</t-link
        >
      </template>
        
       
      </t-table>

      <div class="element-drawer__button">
        <t-button  block @click="listenerFormModelVisible = false">取 消</t-button>
        <t-button  block theme="primary" @click="saveListenerConfig">保 存</t-button>
      </div>
    </t-drawer>

    <!-- 注入西段 编辑/创建 部分 -->
    <t-dialog
      header="字段配置"
      v-model:visible="listenerFieldFormModelVisible"
      width="600px"
      append-to-body
      destroy-on-close
    >
      <t-form
        :data="listenerFieldForm"
        size="small"
        label-width="96px"
        ref="listenerFieldFormRef"
        style="height: 136px"
      >
        <t-form-item
          label="字段名称："
          name="name"
          :rules="[{ required: true, message: '请输入字段名称' }]"
        >
          <t-input v-model:value="listenerFieldForm.name" clearable />
        </t-form-item>
        <t-form-item
          label="字段类型："
          name="fieldType"
          :rules="[{ required: true, message: '请选择字段类型' }]"
        >
          <t-select v-model:value="listenerFieldForm.fieldType">
            <t-option
              v-for="i in Object.keys(fieldTypeObject)"
              :key="i"
              :label="fieldTypeObject[i]"
              :value="i"
            />
          </t-select>
        </t-form-item>
        <t-form-item
          v-if="listenerFieldForm.fieldType === 'string'"
          label="字段值："
          name="string"
          key="field-string"
          :rules="[{ required: true, message: '请输入字段值' }]"
        >
          <t-input v-model:value="listenerFieldForm.string" clearable />
        </t-form-item>
        <t-form-item
          v-if="listenerFieldForm.fieldType === 'expression'"
          label="表达式："
          name="expression"
          key="field-expression"
          :rules="[{ required: true, message: '请输入表达式' }]"
        >
          <t-input v-model:value="listenerFieldForm.expression" clearable />
        </t-form-item>
      </t-form>
      <template #footer>
        <t-button size="small" @click="listenerFieldFormModelVisible = false">取 消</t-button>
        <t-button size="small" theme="primary" @click="saveListenerFiled">确 定</t-button>
      </template>
    </t-dialog>
  </div>

  <!-- 选择弹窗 -->
  <ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
</template>
<script lang="ts" setup>
import { inject, nextTick, ref, watch } from 'vue'
import { createListenerObject, updateElementExtensions } from '../../utils'
import {
  initListenerForm,
  initListenerType,
  eventType,
  listenerType,
  fieldType,
  initListenerForm2
} from './utilSelf'
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
import { DialogPlugin, TableCol } from 'tdesign-vue-next'

defineOptions({ name: 'UserTaskListeners' })

const props = defineProps({
  id: String,
  type: String
})
const prefix = inject('prefix')
const width = inject('width')
const elementListenersList = ref<any[]>([])
const listenerEventTypeObject = ref(eventType)
const listenerTypeObject = ref(listenerType)
const listenerFormModelVisible = ref(false)
const listenerForm = ref<any>({})
const fieldTypeObject = ref(fieldType)
const fieldsListOfListener = ref<any[]>([])
const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态
const editingListenerIndex = ref(-1) // 监听器所在下标，-1 为新增
const editingListenerFieldIndex = ref(-1) // 字段所在下标，-1 为新增
const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单
const bpmnElement = ref()
const bpmnElementListeners = ref()
const otherExtensionList = ref()
const listenerFormRef = ref()
const listenerFieldFormRef = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances

const resetListenersList = () => {
  console.log(
    bpmnInstances().bpmnElement,
    'window.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElementwindow.bpmnInstances.bpmnElement'
  )
  bpmnElement.value = bpmnInstances().bpmnElement
  otherExtensionList.value = []
  bpmnElementListeners.value =
    bpmnElement.value.businessObject?.extensionElements?.values.filter(
      (ex) => ex.$type === `${prefix}:TaskListener`
    ) ?? []
  elementListenersList.value = bpmnElementListeners.value.map((listener) =>
    initListenerType(listener)
  )
}
const openListenerForm = (listener, index?) => {
  if (listener) {
    listenerForm.value = initListenerForm(listener)
    editingListenerIndex.value = index
  } else {
    listenerForm.value = {}
    editingListenerIndex.value = -1 // 标记为新增
  }
  if (listener && listener.fields) {
    fieldsListOfListener.value = listener.fields.map((field) => ({
      ...field,
      fieldType: field.string ? 'string' : 'expression'
    }))
  } else {
    fieldsListOfListener.value = []
    listenerForm.value['fields'] = []
  }
  // 打开侧边栏并清楚验证状态
  listenerFormModelVisible.value = true
  nextTick(() => {
    if (listenerFormRef.value) listenerFormRef.value.clearValidate()
  })
}
// 移除监听器
const removeListener = (listener, index?) => {
    const confirmDia = DialogPlugin({
    body: '确认移除该监听器吗？',
    confirmBtn: '确定',
    cancelBtn: '取消',
    onConfirm: async () => {
    
      bpmnElementListeners.value.splice(index, 1)
      elementListenersList.value.splice(index, 1)
      updateElementExtensions(
        bpmnElement.value,
        otherExtensionList.value.concat(bpmnElementListeners.value)
      )
      confirmDia.hide()
    },
    onClose: () => {
      // 用户点击"取消"或关闭弹窗时的操作
      confirmDia.hide()
    },
    });
}
// 保存监听器
const saveListenerConfig = async () => {
  const validateResult = await listenerFormRef.value.validate()
    if (validateResult !== true) {
      return
    }
  const listenerObject = createListenerObject(listenerForm.value, true, prefix)
  if (editingListenerIndex.value === -1) {
    bpmnElementListeners.value.push(listenerObject)
    elementListenersList.value.push(listenerForm.value)
  } else {
    bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
    elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
  }
  // 保存其他配置
  otherExtensionList.value =
    bpmnElement.value.businessObject?.extensionElements?.values?.filter(
      (ex) => ex.$type !== `${prefix}:TaskListener`
    ) ?? []
  updateElementExtensions(
    bpmnElement.value,
    otherExtensionList.value.concat(bpmnElementListeners.value)
  )
  // 4. 隐藏侧边栏
  listenerFormModelVisible.value = false
  listenerForm.value = {}
}
// 打开监听器字段编辑弹窗
const openListenerFieldForm = (field, index?) => {
  listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
  editingListenerFieldIndex.value = field ? index : -1
  listenerFieldFormModelVisible.value = true
  nextTick(() => {
    if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate()
  })
}
// 保存监听器注入字段
const saveListenerFiled = async () => {
  const validateResult = await listenerFieldFormRef.value.validate()
    if (validateResult !== true) {
      return
    }
  if (editingListenerFieldIndex.value === -1) {
    fieldsListOfListener.value.push(listenerFieldForm.value)
    listenerForm.value.fields.push(listenerFieldForm.value)
  } else {
    fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
    listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
  }
  listenerFieldFormModelVisible.value = false
  nextTick(() => {
    listenerFieldForm.value = {}
  })
}
// 移除监听器字段
const removeListenerField = (field, index) => {
    const confirmDia = DialogPlugin({
      body: '确认移除该字段吗？',
      confirmBtn: '确定',
      cancelBtn: '取消',
      onConfirm: async () => {
    
        fieldsListOfListener.value.splice(index, 1)
        listenerForm.value.fields.splice(index, 1)
        confirmDia.hide()
      },
      onClose: () => {
        // 用户点击"取消"或关闭弹窗时的操作
        confirmDia.hide()
      },
    });
}

// 打开监听器弹窗
const processListenerDialogRef = ref()
const openProcessListenerDialog = async () => {
  processListenerDialogRef.value.open('task')
}
const selectProcessListener = (listener) => {
  const listenerForm = initListenerForm2(listener)
  const listenerObject = createListenerObject(listenerForm, true, prefix)
  bpmnElementListeners.value.push(listenerObject)
  elementListenersList.value.push(listenerForm)

  // 保存其他配置
  otherExtensionList.value =
    bpmnElement.value.businessObject?.extensionElements?.values?.filter(
      (ex) => ex.$type !== `${prefix}:TaskListener`
    ) ?? []
  updateElementExtensions(
    bpmnElement.value,
    otherExtensionList.value.concat(bpmnElementListeners.value)
  )
}
const elementListenersColumns: TableCol[] = [
  { colKey: 'index', title: '序号', width:60},
  { colKey: 'event', title: '事件类型',ellipsisTitle: true },
  { colKey: 'id', title: '事件id',ellipsisTitle: true, },
  { colKey: 'listenerType', title: '监听器类型',ellipsisTitle: true, },
  { colKey: 'operation', title: '操作', width: 100, fixed: 'right' },
].map(column => ({ ...column, align: 'center' }));
const columns: TableCol[] = [
  { colKey: 'index', title: '序号', width:50},
  { colKey: 'name', title: '字段名称' },
  { colKey: 'fieldType', title: '字段类型',ellipsisTitle: true, },
  { colKey: 'string', title: '字段值/表达式',ellipsisTitle: true, },
  { colKey: 'operation', title: '操作', width: 100, fixed: 'right' },
].map(column => ({ ...column, align: 'center' }));
watch(
  () => props.id,
  (val) => {
    val &&
      val.length &&
      nextTick(() => {
        resetListenersList()
      })
  },
  { immediate: true }
)
</script>
